
/* 

 	Declare Class CMD/Constructor - Meaning AjaxLab.Cmd = function is both
		a class declaration, as well as contructor method. 
		
	The default parameter eventhough is not shown passed in, but it's there 
		by default. It's called 'arguments' which is an array object. 
		
	Because it's a class, we can declar private variables, public properties. 
		for example, var copyright is my private variable
					 this.getCopyRight is my public property. 
	
	Because it's a construtor as well,  I can also call any method when get instantiated. 
		for example
*/
Type.registerNamespace("AjaxLab");

var commandListernerStack               =   new Object();
var documentationListnerStack           =   new Object();
var historyQueue                        =   new Object();
var root                                =   "/";
	
AjaxLab.Cmd= function(CommandPromptContainer, CommandPromptTextArea, DebugArea)
{
			this.charactercount                     =   0;
			this.scriptsIncluded                    =   false;
			this.testvalue							=	"public variable";
			
			/* Declare private class variables */
			var promptSeparator						=	":\\>";
			var commandpromptID                     =   "CommandPrompt";
            var commandPrompt                       =    $(commandpromptID);
			var copyright                           =   "AjaxLab Web Command Prompt 1.0 (LGPL) \n" +
														 "<C> CopyRighted 2006 AjaxLab.com \n";
														 
			var isDebug                             =   false;
			var debug_area							=	"debugZone";
  		 	var instance                            =   this;
			/* Call My Own "Constructor" so to speak */
			
	
			
			/* Declare public class properties */
			
			this.getPromptSeparator = function()
			{
				return promptSeparator;
			}
			
			this.getCopyRight = function()
			{
				return copyright;
			}
			
			this.setIsDebug = function (isdebugParam)
			{
				isDebug = isdebugParam;
			}
			
			this.setDebugZone								=	function(debugZone)
			{
				debug_area		=	debugZone;
			}
			
			this.getDebugZone								=	function()
			{
				return $(debug_area);
			}
			
			this.setCommandPromptID                         =    function(commandPromptIDParam)
            {
                commandpromptID =   commandPromptIDParam;
            }
    
            this.getCommandPromptID                         =    function()
            {
                return commandpromptID;
            }

			this.setCommandPrompt                         =    function(commandPromptIDParam)
            {
                commandpromptID =   commandPromptIDParam;
            }
			
            this.getCommandPrompt                           =    function()
            {
                return $(commandpromptID);
            }

            this.setCopyright                               =    function(copyrightParam)
            {
                copyright = copyrightParam;
            }
            this.getCopyright                               =    function(){
                return copyright;
            }

            this.setRoot                                    =    function(rootParam){
                root    =   rootParam;
            }

            this.getRoot                                    =    function(){
                return root;
            }
            
			/*
            this.rePosition                                 =    function(){
                var content = instance.getCommandPrompt();
                Trim_Trailing_LineFeed(content);
                scrollElementToEnd(content);
            }
			
            
            this.Trim                                       =   function(myString)
            {   
                return  Trim_Trailing_LineFeed_Helper(myString);
            }
			
			*/
			
			/* 
				Private Functions 
				
				Why are they private? how are they different from the public class properties above? 
				Notice these function don't have this.* = in front of them. The object instantied
					this class wont' be able to access these class. Tha'ts why they are private
			
			*/
	 
	 		function Debug(value)
            {
                if(isDebug)
                {
                    $(instance.getDebugZone()).innerHTML = value+"<br/>"+$(instance.getDebugZone()).innerHTML;
                }
            }
            
			function Trim(myString)
            {   
                return  Trim_Trailing_LineFeed_Helper(myString);
            }
			
            function Trim_Trailing_LineFeed_Helper(s)
            {
                if(s!=null)
                {
                    while( (s.charCodeAt(s.length-1) == 10) || (s.charCodeAt(s.length-1) == 13) )
                    {
                        s = s.substring(0,s.length-1);
                    }
                }
                return s;
            }

            function Trim_Trailing_LineFeed(element){
                var s = element.value;  
                s = Trim_Trailing_LineFeed_Helper(s);
                element.value=s;
            }
    
            function scrollElementToEnd(element){
                if (typeof element.scrollTop != 'undefined' &&
                   typeof element.scrollHeight != 'undefined') {
                 element.scrollTop = element.scrollHeight;
               }
            }
	
	    	function rePosition()
			{
                var content = instance.getCommandPrompt();
                Trim_Trailing_LineFeed(content);
                scrollElementToEnd(content);
            }
			
	  		function setKeyDownEvent(e)
			{
				Debug("key down");
                var characterCode
                var text                    = instance.getCommandPrompt();
                if(e && e.which)
                { 
                    characterCode = e.which 
                }
                else if(document.getElementById)
                {
                     characterCode = e.keyCode
                var commandListernerStack   = instance.getRegisterCommandListener();
                 
                }
                else{
                    characterCode = event.keyCode 
                }
                //alert(characterCode);
                if(characterCode!=13 && characterCode!=8 && characterCode!=38)  //As long as it's not a backspace or carriage return.
                {   
                   instance.charactercount++; 
                }
                else if (characterCode ==8){
                     instance.charactercount--; 
                     if (instance.charactercount < 0)
                     {
                        text.value = text.value+">";
                        instance.charactercount = 0;
                     }
                }
                else if(characterCode==38){ //upper arrow key left:37 right:39 down:40
                    text.value=text.value;
                }
                else if(characterCode == 13) //If carriage return is pressed.
                {   
                    var commandstring = Trim(text.value);
                    var inputtext   = commandstring.substring(commandstring.length-instance.charactercount); 
                    var command     = inputtext.split(" ");
					Debug(command[0]);
   					if(commandListernerStack==null)
					{
						if(inputtext=="")
						{
							instance.newPrompt();
						}
						else if(command[0].toUpperCase() == "CLEAR" || command[0].toUpperCase() == "CLS")
						{
							Debug("Clear detected");
							if(command[1]==null)
							{
								instance.clearScreen();
							}
							else if(command[1].toUpperCase() == "DEBUG")
							{
								Debug("Clear Debug detected");
								instance.EmptyDebugZone();
							}
						}
						else if(command[0].toUpperCase()=="CD")
						{
							if(command[1]!="")
							{
								instance.cd(command[1]);
							}
						}
						else{
							Debug("No Command Found");
							instance.printToConsole(inputtext+" is not recognized as an internal or external command");
						}
					}
					else{
						if(commandListernerStack[command[0]]==null)
						{
							if(command[0]!="")
							{
								command[0] = "NOTFOUND";    
							}
						}
						if(command[0]=="MAN")
						{
						   
						}
						else{
							commandListernerStack[command[0]](text,command[0],inputtext); //Call the appropriate function associated with the command
						}
					}
                    instance.charactercount=0;
                }
            }
        
            function setKeyUpEvent(e)
			{
 			   Debug("key up");
               if(e && e.which)
                { 
                    e = e
                    characterCode = e.which 
                }
                else{
                    e = event
                    characterCode = e.keyCode 
                }
                if(characterCode == 13)
                {   
                	//instance.newPrompt();
					rePosition();
                }
            }
			
			/* 
				Protected Function 
				1) Are these public functions just like prototype.* public funtions? Inherited class can
					access these fucntions only or prototyp.* public functions as well?
				2) In this case, what's the difference between public function and public properties?
				3) The reaosn I created this is because prototype.insertLibIntoHeadSection() try to call
					this method. if it were a private function (without this.* = ), it won't recongize it
				4) Now that it's public, it servers teh same purpose as protpty.insertLibIntoheaderSectin(),
					is this necesary? or when inherited class comes in, it makes a difference?
			*/
			
			this.includeLibs		=	function()
			{
				  var CommandsLibrary=new Array(
									"SOTAScript/util/CommandPrompt/CommandLibrary/Class_Base.js",
									"SOTAScript/util/CommandPrompt/CommandLibrary/Class_RSS.js",
									"SOTAScript/util/CommandPrompt/CommandLibrary/Class_ToDo.js",
									"SOTAScript/util/Class_DragCommandPrompt.js"
									);
				  instance.insertLibsIntoHTML(CommandsLibrary);
			}
			
			this.insertLibsIntoHTML		=	function insertLibsIntoHTML(CommandsLibrary)
			{
				 if(CommandsLibrary!=null)
				 {
					  var x; 
					  for(x=0; x<CommandsLibrary.length;x++)
					  {
						with (document.getElementsByTagName("head")[0].appendChild(document.createElement("script")))
						{
							setAttribute("type", "text/javascript", 0);
							setAttribute("src", CommandsLibrary[x], 0);
						}
					  }
				 }
			}	

            this.addDefautlKeyListener                      =      function(){
                if (navigator.userAgent.indexOf("Safari") > 0) {
                    instance.getCommandPrompt().addEventListener("keydown", setKeyDownEvent,false);
                    instance.getCommandPrompt().addEventListener("keyup",setKeyUpEvent,false);
                } else if (navigator.product == "Gecko") {
                    instance.getCommandPrompt().addEventListener("keypress",setKeyDownEvent,false);
                    instance.getCommandPrompt().addEventListener("keyup",setKeyUpEvent,false);  
                } else {
                    instance.getCommandPrompt().attachEvent('onkeydown',setKeyDownEvent);
                    instance.getCommandPrompt().attachEvent('onkeyup',setKeyUpEvent);
                }
            }
        
			/*
			
            this.setKeyDownEvent                            =      function(e){
				Debug("key down");
                var characterCode
                var text                    = instance.getCommandPrompt();
                if(e && e.which)
                { 
                    characterCode = e.which 
                }
                else if(document.getElementById)
                {
                     characterCode = e.keyCode
                var commandListernerStack   = instance.getRegisterCommandListener();
                 
                }
                else{
                    characterCode = event.keyCode 
                }
                //alert(characterCode);
                if(characterCode!=13 && characterCode!=8 && characterCode!=38)  //As long as it's not a backspace or carriage return.
                {   
                   instance.charactercount++; 
                }
                else if (characterCode ==8){
                     instance.charactercount--; 
                     if (instance.charactercount < 0)
                     {
                        text.value = text.value+">";
                        instance.charactercount = 0;
                     }
                }
                else if(characterCode==38){ //upper arrow key left:37 right:39 down:40
                    text.value=text.value;
                }
                else if(characterCode == 13) //If carriage return is pressed.
                {   
                    var commandstring = instance.Trim(text.value);
                    var inputtext   = commandstring.substring(commandstring.length-instance.charactercount); 
                    var command     = inputtext.split(" ");
					Debug(command[0]);
   					if(commandListernerStack==null)
					{
						if(inputtext=="")
						{
							instance.newPrompt();
						}
						else if(command[0].toUpperCase() == "CLEAR")
						{
							Debug("Clear detected");
							if(command[1]==null)
							{
								instance.clearScreen();
							}
							else if(command[1].toUpperCase() == "DEBUG")
							{
								Debug("Clear Debug detected");
								instance.EmptyDebugZone();
							}
						}
						else if(command[0].toUpperCase()=="CD")
						{
							if(command[1]!="")
							{
								instance.cd(command[1]);
							}
						}
						else{
							Debug("No Command Found");
							instance.printToConsole(inputtext+" is not recognized as an internal or external command");
						}
					}
					else{
						if(commandListernerStack[command[0]]==null)
						{
							if(command[0]!="")
							{
								command[0] = "NOTFOUND";    
							}
						}
						if(command[0]=="MAN")
						{
						   
						}
						else{
							commandListernerStack[command[0]](text,command[0],inputtext); //Call the appropriate function associated with the command
						}
					}
                    instance.charactercount=0;
                }
            }
        
            this.setKeyUpEvent                   =  function(e){
 			   Debug("key up");
               if(e && e.which)
                { 
                    e = e
                    characterCode = e.which 
                }
                else{
                    e = event
                    characterCode = e.keyCode 
                }
                if(characterCode == 13)
                {   
                	//instance.newPrompt();
					instance.rePosition();
                }
            }
	
			*/
			
			this.newPrompt						=	function()
			{
				var text = instance.getCommandPrompt().value;
				
				text = text + "\n"+instance.getRoot()+":\\>";
				instance.getCommandPrompt().value = text;
				instance.charactercount=0;
			}
			
			instance.PreLoad(arguments);
}

AjaxLab.Cmd.registerClass('AjaxLab.Cmd', null, null);




/* 

	Below are the public funtions 

*/




AjaxLab.Cmd.prototype = {
	
		/* Accepts an array object */
	 	PreLoad							:	function(arguments)
		{
				//this.includeLibs();
				Debug("PreLoad");
				scriptsIncluded  = true;
                if(arguments.length>2){
                    this.setCommandPrompt(arguments[1]);
					this.setDebugZone(arguments[2]);
					this.setRoot(arguments[3]);
                }
				this.clearScreen();
                this.addDefautlKeyListener();
		}, 
		
		emptyScreen					:	 function()
		{
				this.getCommandPrompt().value = "";
		},
		
		clearScreen					: 	 function()
		{
				this.emptyScreen();
				this.print(this.getCopyright());
                this.println();
                this.print(this.getRoot());
                this.print(this.getPromptSeparator());
		},
		
		EmptyDebugZone				:	function()
		{
				this.getDebugZone().innerHTML = "";
				this.println();
				this.print(this.getRoot());
				this.print(this.getPromptSeparator());
		},
		
	  	appendToConsole:            function (myValue){
            
            var myField         =   this.getCommandPrompt();
            if(myField!=null)
            {
                if (document.selection) {
                    myField.focus();
                    sel = document.selection.createRange();
                    sel.text = myValue;
                }
                else if (myField.selectionStart || myField.selectionStart == '0') {
                    var startPos = myField.selectionStart;
                    var endPos = myField.selectionEnd;
                    myField.value = myField.value.substring(0, startPos)+ myValue+ myField.value.substring(endPos, myField.value.length);
                } else {
                    myField.value += myValue;
                }
            }
        },  
           
        cd    :                     function(valueParam)
        {
            this.setRoot(valueParam);
			this.newPrompt();
        },
 
        print :                     function(valueParam)
		{
            this.appendToConsole(valueParam);
        }, 

		println:					function(valueParam)
		{
			var value = "";
			if(valueParam!=null)
			{
				value = valueParam;
			}
			value = value+"\n";
			this.appendToConsole(value);
		}, 
	
		printToConsole:             function(valueParam){
			this.println();
            this.println(valueParam);
			this.println();
            this.print(this.getRoot()+this.getPromptSeparator());
        },
		
        println2:                    function(){
            var length = arguments.length;
            var value  = "";
    
            if(length>0)
            {
                value = "\n\n"+arguments[0]+"\n\n";
            }
            else{
                value = "\n";
            }
            this.appendToConsole(value);

        },    
       	
	
		printToConsole2:             function(valueParam){
            this.println(valueParam);
            this.print(this.getRoot()+">");
        },
		
		insertLibIntoHeadSection  		:    function (CommandsLibrary)
		{	
			 if(CommandsLibrary!=null)
			 {
				 this.insertLibsIntoHTML(CommandsLibrary);
			 }
		},
		
        setRegisterCommandListener:     function(CommandNames, commandListenerFunction, commandDocumentationFunction){
                var commandarray = CommandNames.split("|");
                var x = 0;
                for (x=0; x<commandarray.length;x++)
                {
                    commandListernerStack[commandarray[x].toUpperCase()]= commandListenerFunction;
                    documentationListnerStack[commandarray[x].toUpperCase()]= commandDocumentationFunction;
                }
        },
            
        getRegisterCommandListener:     function(){
                return commandListernerStack;
        }
}
	